package com.inspinia.base.util;

import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.lang3.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Map;

/**
 * Freemarker操作类
 *
 * @author fengwx
 */
public class FreemarkerUtils {

    /**
     * 日志对象
     */
    private static Logger logger = LoggerFactory.getLogger(FreemarkerUtils.class);

    /**
     * 根据表达式模版生成内容。如果解析出错会返回表达式的原字符串
     *
     * @param data 参数
     * @param expr 表达式
     * @return string
     */
    public static String parse(Object data, String expr) {
        try {
            StringTemplateLoader stringLoader = new StringTemplateLoader();
            stringLoader.putTemplate("tpl", expr);

            Configuration cfg = new Configuration();
            cfg.setTemplateLoader(stringLoader);
            cfg.setClassicCompatible(true); // 忽略找不到的变量
            Template template = cfg.getTemplate("tpl");

            StringWriter writer = new StringWriter();
            template.process(data, writer);
            writer.flush();
            return writer.toString();
        } catch (Exception e) {
            logger.error("", e);
        }
        return expr;
    }

    /**
     * 将文件用freemarker替换
     *
     * @param object         map对象
     * @param tempFolder     模板文件所在文件夹路径(不包含文件名)
     * @param targetFilePath 生成文件路径(包含文件名)
     * @param tempName       模板文件名
     * @throws IOException
     * @throws TemplateException
     */
    public static void replaceToFile(Object object, String tempFolder, String targetFilePath, String tempName){
        String content = JsonUtils.toJson(object);
        content=StringEscapeUtils.unescapeHtml4(content);
        content=content.replace("&","&amp;");
        content=content.replace("<","&lt;");
        content=content.replace(">","&gt;");
        object=JsonUtils.fromJson(content,Object.class);
        Configuration configuration = new Configuration();
        try {
            configuration.setDirectoryForTemplateLoading(new File(tempFolder));
            configuration.setClassicCompatible(true); // 忽略找不到的变量
            FileUtil.createFolder(targetFilePath);
            Template temp = configuration.getTemplate(tempName, "utf-8");
            Map<String, Object> map = null;
            if (object instanceof Map) {
                map = (Map<String, Object>) object;
            } else {
                map = BeanUtil.object2Map(object);
            }
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                if (map.get(entry.getKey()) instanceof String) {
                    map.put(entry.getKey(), enter((String) map.get(entry.getKey())));
                }
            }
//            Iterator<String> iterator = map.keySet().iterator();
//            while (iterator.hasNext()) {
//                String key;
//                Object value;
//                key = iterator.next().toString();
//                value = map.get(key);
//              if (value instanceof List) {
//                    List list = (List) value;
//                    for (int i = 0; i < list.size(); i++) {
//                        Object ob = list.get(i);
//                        if (ob instanceof String) {
//                            if (ob.equals("0")) {
//                                ob = "";
//                            }
//                        } else if (ob instanceof Map) {
//                            Map<String, Object> map1 = (Map<String, Object>) ob;
//                            Iterator<String> iterator1 = map1.keySet().iterator();
//                            while (iterator1.hasNext()) {
//                                String key1;
//                                Object value1;
//                                key1 = iterator1.next().toString();
//                                value1 = map.get(key1);
//                                if (value1 instanceof String) {
//                                    if (value1.equals("0")) {
//                                        map1.put(key, "");
//                                    }
//                                }
//                            }
//                            ob = map1;
//                        } else {
//                            Class<?> aClass = ob.getClass();
//                            Field[] fields = aClass.getDeclaredFields();
//                            for (int j = 0; j < fields.length; j++) {
//                                Field field = fields[j];
//                                field.setAccessible(true);
//
//                                if (field.get(ob) != null && !"".equals(field.get(ob).toString())) {
//                                    String fname = field.getName();
//                                    fname = fname.substring(0, 1).toUpperCase() + fname.substring(1);
//                                    String type = field.getGenericType().toString(); // 获取属性的类型
//                                    if (type.equals("class java.lang.String")) { // 如果type是类类型，则前面包含"class "，后面跟类名
//                                        Method m = ob.getClass().getMethod("get" + fname);
//                                        String valuef = (String) m.invoke(ob); // 调用getter方法获取属性值
//                                        if (valuef == null || valuef.equals("0")) {
//                                            m = ob.getClass().getMethod("set"+fname,String.class);
//                                            m.invoke(ob, "");
//                                        }
//                                    }
//                                    if (type.equals("class java.lang.Integer")) {
//                                        if (fname.equals("GDownNum")) {
//                                            fname = "gDownNum";
//                                        }
//                                        Method m = ob.getClass().getMethod("get" + fname);
//                                        Integer valuef = (Integer) m.invoke(ob);
//                                        if (valuef == null || valuef.equals(0)) {
//                                            m = ob.getClass().getMethod("set"+fname,Integer.class);
//                                            m.invoke(ob, 0);
//                                        }
//                                    }
//
//                                    if (type.equals("class java.math.BigDecimal")) {
//                                        Method m = ob.getClass().getMethod("get" + fname);
//                                        BigDecimal valuef = (BigDecimal) m.invoke(ob);
//                                        if (valuef == null || valuef.equals(0)) {
//                                            m = ob.getClass().getMethod("set"+fname,BigDecimal.class);
//                                            m.invoke(ob, 0);
//                                        }
//                                    }
//                                    if (type.equals("class java.lang.Long")) {
//                                        Method m = ob.getClass().getMethod("get" + fname);
//                                        Long valuef = (Long) m.invoke(ob);
//                                        if (valuef == null || valuef.equals(0)) {
//                                            m = ob.getClass().getMethod("set"+fname,Long.class);
//                                            m.invoke(ob, 0);
//                                        }
//                                    }
//                                }
//
//                            }
//                        }
//                        list.set(i, ob);
//                        value = list;
//                        map.put(key, value);
//
//                    }
//                }
//
//            }
            FileOutputStream fos = new FileOutputStream(targetFilePath);
            Writer writer = new OutputStreamWriter(fos, "utf-8");
            temp.process(map, writer);
            fos.close();
            writer.close();
        } catch (Exception e) {
            logger.error("", e);
        }
    }

    /**
     * 将xml文档生成为docx文档
     *
     * @param object
     * @param tempFolder
     * @param targetFilePath
     * @param tempName
     * @throws Exception
     */

    public static String replaceToDocx(Object object, String tempFolder, String targetFilePath, String tempName) {
        String filename = targetFilePath.substring(0, targetFilePath.lastIndexOf(".")) + ".xml";
        replaceToFile(object, tempFolder, filename, tempName);
//        FileUtil.xml2docx(filename+".xml",targetFilePath);
        return WordHelper.xml2Docx(filename);
    }

    /**
     * 把字符串的\r\n替换为可以在office中可以换行需要的xml代码
     *
     * @param text
     * @return
     */
    public static String enter(String text) {
        String str = "</w:t>\n" +
                "                                    </w:r>\n" +
                "                                </w:p>\n" +
                "                                <w:p w:rsidR=\"00082400\" w:rsidRPr=\"009450DC\" w:rsidRDefault=\"00082400\"\n" +
                "                                     w:rsidP=\"00754248\">\n" +
                "                                    <w:pPr>\n" +
                "                                        <w:spacing w:line=\"0\" w:lineRule=\"atLeast\"/>\n" +
                "                                        <w:jc w:val=\"left\"/>\n" +
                "                                        <w:rPr>\n" +
                "                                            <w:rFonts w:ascii=\"仿宋\" w:eastAsia=\"仿宋\" w:hAnsi=\"仿宋\" w:cs=\"仿宋_GB2312\"/>\n" +
                "                                            <w:sz w:val=\"21\"/>\n" +
                "                                        </w:rPr>\n" +
                "                                    </w:pPr>\n" +
                "                                    <w:r w:rsidRPr=\"009450DC\">\n" +
                "                                        <w:rPr>\n" +
                "                                            <w:rFonts w:ascii=\"仿宋\" w:eastAsia=\"仿宋\" w:hAnsi=\"仿宋\" w:cs=\"仿宋_GB2312\"\n" +
                "                                                      w:hint=\"eastAsia\"/>\n" +
                "                                            <w:sz w:val=\"21\"/>\n" +
                "                                        </w:rPr>\n"+
                "                                        <w:t>";
        if (FileUtil.isBase64(text)) {
            return text;
        } else {
            text = combineMultiLine(text);
            return text.replaceAll(System.getProperty("line.separator", "\n"), str);
        }
    }

    /**
     * 合并多行（去掉多余的无用的回车换行）
     * @param s
     * @return
     */
    private static String combineMultiLine(String s) {
        if (StringUtils.isNotEmpty(s)) {
            String lineSeparator = System.getProperty("line.separator", "\n");
            String regex = "(" + lineSeparator + ")+";
            return s.replaceAll(regex, lineSeparator);
        }
        return s;
    }

}
